#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#include <netinet/in.h>
#include <arpa/inet.h>

#include <libgen.h> // POSIX library for basename

#include "MyScpDefine.h"

bool isNumber(const std::string& str) 
{
    for (char c : str) {
        if (c < '0' || c > '9') {
            return false;
        }
    }
    return true;
}


int ShowHelpMessage()
{
    printf("ShowHelpMessage()\n");

    return 0;
}

int main(int argc, char **argv)
{
    printf("argc = %d\n", argc);

    int nPort = 9527;
    std::string strArgv1;
    if (argc == 2)
    {
        printf("88888888888888888\n");

        strArgv1 = std::string(argv[1]);
        if ( (strArgv1 == "-h") || (strArgv1 == "-H") )
        {
            ShowHelpMessage();
            return 0;
        }

        printf("========== Scp Server Running ========== \n");

        if (isNumber(strArgv1))
        {
            int nTmpPort = atoi(argv[1]);

            // available 1024 ~ 65535
            if ( (nTmpPort >= 1024) && (nTmpPort < 65535) )
            {
                nPort = nTmpPort;
            }
        }
    }


    //================socket()
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd == -1)
    {
        printf("socket error\n");
        return -1;
    }

    // 设置端口复用 ( bind error 发生这种情况是在服务端主动关闭连接以后，接着立即启动就会出现这种错误)
    int opt = 1;
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));

    // 定义一个结构体来存放服务器（本机）的信息，用于bind()
    struct sockaddr_in ipAddr;
    memset(&ipAddr, 0, sizeof(ipAddr));

    ipAddr.sin_family = AF_INET;                // 协议
    ipAddr.sin_port = htons(nPort);             // 端口号
    ipAddr.sin_addr.s_addr = htonl(INADDR_ANY); // 本机的IP地址

    //================bind()
    int ret = bind(fd, (struct sockaddr *)&ipAddr, sizeof(ipAddr));
    if (ret == -1)
    {
        printf("bind error\n");
        return -1;
    }

    //================listen()
    ret = listen(fd, 0);
    if (ret == -1)
    {
        printf("bind error\n");
        return -1;
    }

    struct sockaddr_in clientInfo;
    memset(&clientInfo, 0, sizeof(clientInfo));
    int len = sizeof(clientInfo);

    char recvBuf[1024] = {0};

    int newSocketFd = accept(fd, (struct sockaddr *)&clientInfo, (socklen_t *)&len);
    if (newSocketFd == -1) 
    {
        perror("accept error");
        return -1;
    }

    // 接收文件名和文件大小
    read(newSocketFd, recvBuf, sizeof(recvBuf));
    printf("Received file Path: %s\n", recvBuf);

    std::string strNewFileName = basename(recvBuf);
    printf("Received file Name: %s\n", strNewFileName.c_str());


    memset(recvBuf, 0 , sizeof(recvBuf));

    read(newSocketFd, recvBuf, sizeof(recvBuf));
    int file_size = atoi(recvBuf);
    printf("Received file size: %d bytes\n", file_size);

    // 接收文件内容并保存到本地文件
    FILE *file = fopen(strNewFileName.c_str(), "wb");
    if (file == NULL) 
    {
        perror("fopen error");
        return -1;
    }

    int received_bytes = 0;
    while (received_bytes < file_size) 
    {
        int bytes_received = read(newSocketFd, recvBuf, sizeof(recvBuf));
        if (bytes_received <= 0) 
        {
            perror("recv error");
            break;
        }
            
        fwrite(recvBuf, 1, bytes_received, file);
        received_bytes += bytes_received;
        printf("this time read %d Bytes, total %d Bytes\n", bytes_received, received_bytes); 
    }

    close(fd);
    close(newSocketFd);

    fclose(file);


    return 0;
}